﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wedo.Recognition.Domain;
using System.Data.Entity; 

using Wedo.Service.Common;
using Wedo.Utility;
using Wedo.Domain.Models;  
using Wedo.Recognition.Repository;


namespace Wedo.Service.Common
{
    public class BaseService<T> : IBaseService<T>
        where T : class 
    {
        protected IUnitWork _dbContext;
        protected IRepository<T> _repository;
        public BaseService(IUnitWork dbContext, IRepository<T> repository)
        {
            _dbContext = dbContext;
            _repository = repository;
        }

        public virtual T Add(T entity)
        {
            var model= _repository.Create(entity);
            Commit();
            return model;
        }


        public virtual T Update(T entity)
        {
            var model = GetOldModel(entity);
            model.CheckNull();

            UpdateBefore(model, entity);
            _repository.UpdateProperties(model, entity);

            UpdateAfter(model, entity);

            Commit();
            return model;

        }

        /// <summary>
        /// 修改前，可以用来保持原数据不修改，如创建时间等
        /// </summary>
        /// <param name="old"></param>
        /// <param name="news"></param>
        protected virtual void UpdateBefore(T old, T news)
        {

        }

        /// <summary>
        /// 修改后，可以用来修改外键数据
        /// </summary>
        /// <param name="old"></param>
        /// <param name="news"></param>
        protected virtual void UpdateAfter(T old, T news)
        {

        }

        public virtual void Remove(object id)
        {
            _repository.Delete(id);
            Commit();

        }

        public IQueryable<T> GetAll(System.Linq.Expressions.Expression<Func<T, bool>> where = null, string includes = null)
        {
            return _repository.Get(where, null, includes);
        }

        public T GetById(object id)
        {
            return _repository.Find(id);
        }

        public void Commit()
        {
            _dbContext.SaveChanges();
        }

        public IQueryable<T> All()
        {
            return _repository.All();
        }

        protected T GetOldModel(T entity)
        {
            var id = entityKey(entity);
            return GetById(id);
        }

        protected virtual object entityKey(T entity)
        {
            var idvalue = entity.GetType().GetProperty("Id").GetValue(entity, null);
            return idvalue;
        }

    }
}